package com.hu.bgp.server;

import java.io.File;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import com.hu.bgp.server.domain.Profile;

/**
 * Deze singleton beheert alle gametypes, games, enzovoort.
 * 
 * @author ejvos
 */
public class GameServerContext
{
	private static final String CONTEXT_KEY = "GameServer";
	private static final String PROFILE_ID_KEY = "ProfileId";
	private static final String PLAYER_UUID_KEY = "PlayerUuid";

	public static synchronized GameServerContext getInstance(ServletContext servletContext)
	{
		Object object = servletContext.getAttribute(CONTEXT_KEY);
		GameServerContext instance = null;
		if (object == null || !(object instanceof GameServerContext))
		{
			instance = new GameServerContext(servletContext);
			servletContext.setAttribute(CONTEXT_KEY, instance);
		}
		else
		{
			instance = (GameServerContext) object;
		}
		return instance;
	}

	private GameTypeCollection gameTypeCollection = new GameTypeCollection();
	private PlayerCollection playerCollection = new PlayerCollection();
	private BgpConfiguration configuration;
	private BarLoader barLoader;
	private BarFileSystemWatcher bfsWatcher;
	private String playerClientModulePath;
	private String scoreClientModulePath;
	private Persistence persistence;

	private GameServerContext(ServletContext servletContext)
	{
		configuration = new BgpConfiguration(servletContext);
		bfsWatcher = new BarFileSystemWatcher(this);
		barLoader = new BarLoader(this);
		persistence = new Persistence(this);
		persistence.init();
		bfsWatcher.start();
		playerClientModulePath = servletContext.getRealPath("/playerclient");
		scoreClientModulePath = servletContext.getRealPath("/scoreclient");
	}

	public GameTypeCollection getGameTypeCollection()
	{
		return gameTypeCollection;
	}

	public PlayerCollection getPlayerCollection()
	{
		return playerCollection;
	}

	public BgpConfiguration getConfiguration()
	{
		return configuration;
	}

	public BarLoader getBarLoader()
	{
		return barLoader;
	}

	public Persistence getPersistence()
	{
		return persistence;
	}

	public File getResourcesFileByContextPath(String contextPath)
	{
		String resourcesUrlPrefix = configuration.getResourcesUrlPrefix();
		String playerClientUrlPrefix = configuration.getPlayerClientUrlPrefix();
		String scoreClientUrlPrefix = configuration.getScoreClientUrlPrefix();
		File file = null;
		if (contextPath.startsWith(resourcesUrlPrefix))
		{
			String path = contextPath.substring(resourcesUrlPrefix.length());

			int firstSlash = path.indexOf('/');
			String alias = path.substring(0, firstSlash);
			String resourcePath = path.substring(firstSlash + 1);

			GameType gt = gameTypeCollection.getByAlias(alias);
			file = new File(gt.getBarExtractDir() + File.separator + configuration.getBarResourceDirName() + File.separator + resourcePath);
		}
		else if (contextPath.startsWith(playerClientUrlPrefix))
		{
			String path = contextPath.substring(playerClientUrlPrefix.length());
			file = new File(playerClientModulePath + File.separator + path);
		}
		else if (contextPath.startsWith(playerClientUrlPrefix))
		{
			String path = contextPath.substring(playerClientUrlPrefix.length());
			file = new File(playerClientModulePath + File.separator + path);
		}
		else if (contextPath.startsWith(scoreClientUrlPrefix))
		{
			String path = contextPath.substring(scoreClientUrlPrefix.length());
			file = new File(scoreClientModulePath + File.separator + path);
		}
		return file;
	}

	/**
	 * returnt null indien de profile niet gevonden is
	 */
	public Profile getOrCreateCurrentProfile(HttpServletRequest request)
	{
		Profile result = null;
		Object profileIdObj = request.getSession().getAttribute(PROFILE_ID_KEY);
		if (profileIdObj != null)
		{
			// profile id is already stored in the http session
			result = Profile.findForId(persistence, (Integer) profileIdObj);
		}
		else
		{
			// profile uuid is found in the cookie, but profileId not yet stored
			// in session
			String profileUuid = BgpCookieFilterImpl.findUserUuidFromCookie(request);
			if (profileUuid != null)
			{
				result = Profile.findForUuid(persistence, profileUuid);
				if (result == null)
				{
					// uuid was generated, but profile is not yet in the
					// database
					// so lets create a row
					result = new Profile();
					result.setName("Anonymous");
					result.setProfileUuid(profileUuid);
					result.save(persistence);
					// save again to attach the profileId to the name
					result = Profile.findForUuid(persistence, profileUuid);
					result.setName("Anonymous-" + result.getId());
					result.save(persistence);
				}
				// store profile id in the session
				request.getSession().setAttribute(PROFILE_ID_KEY, result.getId());
			}
		}
		return result;
	}

	public Player getOrCreateCurrentPlayer(HttpServletRequest request)
	{
		Player result = null;
		Object uuidObj = request.getSession().getAttribute(PLAYER_UUID_KEY);
		if (uuidObj == null)
		{
			result = new Player(this, getOrCreateCurrentProfile(request));
			playerCollection.add(result);
			// store the UUID in the session
			request.getSession().setAttribute(PLAYER_UUID_KEY, result.getUuidString());
		}
		else
		{
			result = playerCollection.get((String) uuidObj);
		}
		return result;
	}
}
